package org.example.maven.museumuser.utils;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;

import org.apache.commons.lang3.RegExUtils;
import org.example.maven.museumuser.annotation.Anonymous;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 设置Anonymous注解允许匿名访问的url
 *
 */
@Configuration
public class PermitAllUrlProperties  implements SmartInitializingSingleton, ApplicationContextAware {
    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");

    private ApplicationContext applicationContext;

    private List<String> urls = new ArrayList<>();

    public String ASTERISK = "*";


    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.applicationContext = context;
    }

    public List<String> getUrls() {
        return urls;
    }

    public void setUrls(List<String> urls) {
        this.urls = urls;
    }

    @Override
    public void afterSingletonsInstantiated() {
        // 明确指定使用 Spring MVC 的 HandlerMapping
        RequestMappingHandlerMapping mapping = applicationContext.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        System.out.println("Total mapped handler methods: " + map.size());

        map.forEach((info, handlerMethod) -> {
            Method method = handlerMethod.getMethod();

            // 方法上的 @Anonymous
            Anonymous annoOnMethod = AnnotationUtils.findAnnotation(method, Anonymous.class);
            if (annoOnMethod != null) {
                System.out.println("Found @Anonymous on method: " + method.getName());

                Optional.ofNullable(info.getPatternsCondition())
                        .map(PatternsRequestCondition::getPatterns)
                        .ifPresent(patterns -> {
                            System.out.println("Patterns for " + method.getName() + ": " + patterns);

                            if (patterns.isEmpty()) {
                                System.err.println("⚠️ Warning: No patterns found for method annotated with @Anonymous");
                                return;
                            }

                            patterns.forEach(url -> {
                                String replaced = RegExUtils.replaceAll(url, PATTERN, ASTERISK);
                                urls.add(replaced);
                                System.out.println("Added URL: " + replaced);
                            });
                        });
            }

            // 类上的 @Anonymous
            Anonymous annoOnClass = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
            if (annoOnClass != null) {
                System.out.println("Found @Anonymous on class: " + handlerMethod.getBeanType().getName());

                Optional.ofNullable(info.getPatternsCondition())
                        .map(PatternsRequestCondition::getPatterns)
                        .filter(p -> !p.isEmpty())
                        .ifPresent(patterns -> patterns.forEach(url -> {
                            String replaced = RegExUtils.replaceAll(url, PATTERN, ASTERISK);
                            urls.add(replaced);
                            System.out.println("Added URL: " + replaced);
                        }));
            }
        });

        System.out.println("Collected anonymous URLs: " + urls);
    }


}


